﻿using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MongoDB.Driver;
using MongoDB.Bson;

namespace sqCore
{
    /* Docs:
    * Summary
       * Query Result object for SqlA.
       * Results organized as tree.
       * Allows Save,Load,Manipulate format and compare results.
    * Variables
       * Params<T> - List of T objects.
    */
    [Serializable]
    public class sqQueryTreeResult<T>
    {
        public List<T> Params { get; set; }

        /* Docs:
        * Summary: Initialize the results object.
        */
        public sqQueryTreeResult(List<T> Params)
        {
            this.Params=Params;
        }
        
        /* Docs:
        * Summary: Checks if the results is empty.
        */
        public bool isEmpty()
        {
            if (this.Params.Count() == 0)
            {
                return true;
            }
            else
                return false;
        }

        /* Docs:
        * Summary: Checks if the results is not empty.
        */
        public bool isNotEmpty()
        {
            if (this.isEmpty())
                return false;
            else
                return true;
        }

        /* Docs:
        * Summary: Returns the number of objects.
        */
        public int numOfItems()
        {
            return this.Params.Count();
        }

        /* Docs:
        * Summary: Checks if item equals to specific item in Params.
        * Variables
            * ItemNum - Index of the specific item in Params.
            * Item - The item to compare to.
        */
        public bool isEquleItem(int ItemNum, T Item)
        {
            if (Params[ItemNum].ToJson().Equals(Item.ToJson()))
                return true;
            else
                return false;            
        }

        /* Docs:
        * Summary: Compares this results to another result.
        * Variables
            * Result - Another result to compare to.
        */
        public sqQueryTreeResult<T>[] compareTqResult(sqQueryTreeResult<T> Result)
        {
            List<T> equles = new List<T>();
            List<T> onlySelf = new List<T>();
            List<T> onlyResult = new List<T>();
            bool r = false;
            bool s = false;
            foreach (T item in Result.Params)
            {
                for (int selfItem = 0; selfItem < this.Params.Count(); ++selfItem)
                    if (this.isEquleItem(selfItem, item))
                    {
                        equles.Add(item);
                        r = true;
                    }
                if (r == false)
                    onlyResult.Add(item);
                r = false;
            }

            for (int selfItem = 0; selfItem < this.Params.Count(); ++selfItem)
            {
                foreach (T item in Result.Params)
                    if (this.isEquleItem(selfItem, item))
                        s = true;
                if (!s)
                    onlySelf.Add(this.Params[selfItem]);
                s = false;
            }
            return new sqQueryTreeResult<T>[3] { new sqQueryTreeResult<T>(equles), new sqQueryTreeResult<T>(onlySelf), new sqQueryTreeResult<T>(onlyResult) };
        }

        /* TODO: REMOVE
        public string parseBsonArry(BsonArray ba, string spaceing = "")
        {
            string result = spaceing + "[<br>" + spaceing + "&nbsp&nbsp&nbsp";
            foreach (BsonValue v in ba)
            {
                if (v.BsonType == BsonType.Document)
                    result += spaceing + " : <br>" + parseBsonDoc((BsonDocument)v, spaceing: spaceing + "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.");
                else if (v.BsonType == BsonType.Array)
                    result += spaceing + "  <br>" + parseBsonArry((BsonArray)v, spaceing: spaceing + "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.");
                else
                    result += v.ToString() + " , ";
                
            }
            result += "<br>"+ spaceing + "] <br>";
            return result;
        }

        public string parseBsonDoc(BsonDocument bd, string spaceing = "")
        {
            string result="";
            foreach (BsonElement el in bd)
            {
                if (el.Value.GetType() == typeof(BsonArray))
                {
                    result += spaceing + el.Name.ToString() + " : <br>" + parseBsonArry((BsonArray)el.Value, spaceing: spaceing + "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.");
                    }
                else if (el.Value.GetType() == typeof(BsonDocument))
                    result += spaceing + el.Name.ToString() + " : <br>" + parseBsonDoc((BsonDocument)el.Value, spaceing: spaceing + "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.");
                else
                    result += spaceing + el.Name.ToString() + " : " + el.Value.ToString() + "<br>";
            }
            return result;
        }*/

        /* Docs:
        * Summary: Formats the Results to HTML format.           
        * Variables
           * AdditionalText - This text will add to the html code, before the result.           
        */
        public string makeHtmlMessage(string AdditionalText)
        {
            string htmlMessage = "<head><title></title></head><body align = center><h3 align=center>" + AdditionalText + "</h3>";
            foreach (T O in Params)
            {
                htmlMessage += sqHelpper.BeautifyJson(O.ToJson());
                htmlMessage += "<br><br>";
            }
            htmlMessage += "</body>";
            return htmlMessage;
        }

        /* Docs:
        * Summary: Formats the Results to XML and save them in file.
        * Variables
           * FilePath - The path to save the file.
        */
        public void makeFile(string FilePath)
        {
            string f = "";
            foreach (T item in this.Params)
                f += sqHelpper.FormatJsonToXML(item.ToJson()).ToString();
            f += "\n\n";
            
            FileStream fs;
            fs = new FileStream(@FilePath, FileMode.Create, FileAccess.Write);
            StreamWriter writer = new StreamWriter(fs);
            writer.Write(f);
            writer.Close();
            fs.Close();


        }

        /* Docs:
        * Summary: Saves in file a copy of this object as json.
        * Variables
           * FilePath - The path to save the file.
        */
        public void makePickle(string FilePath)
        {
            FileStream fs;
            fs = new FileStream(@FilePath, FileMode.Create, FileAccess.Write);
            StreamWriter writer = new StreamWriter(fs);
            writer.Write(sqHelpper.BeautifyJson(this.ToJson()));
            writer.Close();
            fs.Close();
        }
    } //end of sqQueryTreeResult Class
}
